package com.gin.supermarket_inventory_system.inventory.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gin.common.utils.TimeUtils;
import com.gin.supermarket_inventory_system.inventory.dao.SettlementDayPoDao;
import com.gin.supermarket_inventory_system.inventory.entity.InventoryReceiptPo;
import com.gin.supermarket_inventory_system.inventory.entity.SettlementDayPo;
import com.gin.supermarket_inventory_system.inventory.enums.InventoryReceiptType;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 *
 * @since : 2023/10/14 15:28
 * @author : ginstone
 * @version : v1.0.0
 **/
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class SettlementDayServiceImpl extends ServiceImpl<SettlementDayPoDao, SettlementDayPo> implements SettlementDayService {
    private final InventoryReceiptService inventoryReceiptService;

    /**
     * 执行结算
     */
    @Override
    public void settle() {
        // 确定上一次结算的时间
        final ZonedDateTime start = findStart();
        // 结算终止时间
        final ZonedDateTime end = ZonedDateTime.now().withHour(4).withMinute(0).withSecond(0);

        // 统计结果按日期分组
        final Map<String, List<InventoryReceiptPo>> resultMap = inventoryReceiptService.countGroupByType(start.toEpochSecond(), end.toEpochSecond()).stream().collect(Collectors.groupingBy(InventoryReceiptPo::getDate));

        if (resultMap.isEmpty()) {
            return;
        }

        final ArrayList<SettlementDayPo> entities = new ArrayList<>();
        resultMap.forEach((date, list) -> {
            final SettlementDayPo po = new SettlementDayPo();
            po.setDate(date);

            // 销售数据
            list.stream().filter(i -> i.getType() == InventoryReceiptType.SELL).findFirst().ifPresent(i -> {
                po.setCountSell(i.getCount());
                po.setTotalPriceSell(i.getTotalPrice());
            });
            // 销售退货
            list.stream().filter(i -> i.getType() == InventoryReceiptType.CANCEL).findFirst().ifPresent(i -> {
                po.setCountCancel(i.getCount());
                po.setTotalPriceCancel(i.getTotalPrice());
            });
            // 库存进货
            list.stream().filter(i -> i.getType() == InventoryReceiptType.PURCHASE).findFirst().ifPresent(i -> {
                po.setCountPurchase(i.getCount());
                po.setTotalPricePurchase(i.getTotalPrice());
            });
            // 库存退货
            list.stream().filter(i -> i.getType() == InventoryReceiptType.REJECT).findFirst().ifPresent(i -> {
                po.setCountReject(i.getCount());
                po.setTotalPriceReject(i.getTotalPrice());
            });

            entities.add(po);
        });

        saveBatch(entities);


    }

    /**
     * 返回上一次结算的时间
     * @return ZonedDateTime
     */
    public ZonedDateTime findStart() {
        final QueryWrapper<SettlementDayPo> qw = new QueryWrapper<>();
        qw.select("max(date) as date");
        final List<SettlementDayPo> list = list(qw);
        // 没有查询结果，返回0
        if (list.get(0) == null) {
            return ZonedDateTime.ofInstant(Instant.ofEpochSecond(0), ZoneId.systemDefault());
        }
        // 有结果，转换为 ZonedDateTime 返回
        final String date = list.get(0).getDate();
        return TimeUtils.parse(date).plusDays(1).withHour(4).withMinute(0).withSecond(0);
    }

    /**
     * 每天4点执行自动结算
     */
    @Scheduled(cron = "0 0 4 * * ?")
    public void autoSettle() {
        settle();
    }
}
